import React, { useEffect, useState, useMemo } from 'react';
import _ from 'lodash';
import { nanoid } from 'nanoid';
import { Drawer, Spin, Tree, Button, message, Empty } from 'antd';
import { AlignLeftOutlined } from '@ant-design/icons';
import GrainedAuthDrawer from './grainedAuthDrawer';
import DebounceWrapper from '@/components/DebounceWrapper';
import { fetchResourceAuthByRoleId, updateResourceAuthByRoleId } from '@/services/system/role';
import { fetchValidResourceFromTree } from '@/services/system/resource';
import { formatTree } from '@/utils/utils';
import styles from './authDrawer.less';

const DebounceButton = DebounceWrapper(Button);
// 获取子节点Id集合
const getChildIds = (tree = [], arr = []) => {
  if (!tree.length) return [];
  _.forEach(tree, (item) => {
    if (item.children && item.children.length) {
      getChildIds(item.children, arr);
    } else {
      arr.push(item.key);
    }
  });
  return arr;
};
// 获取父节点Id集合
const getFatherIds = (tree = [], arr = []) => {
  if (!tree.length) return [];
  _.forEach(tree, (item) => {
    if (item.children && item.children.length) {
      arr.push(item.key);
      getFatherIds(item.children, arr);
    }
  });
  return arr;
};
// 根据id获取菜单节点名称
const getMenuNameById = (tree, id) => {
  let name;
  const loop = (list, id) => {
    _.forEach(list, (item) => {
      if (item.children && item.children.length) {
        return loop(item.children, id);
      }
      if (item.key === id) {
        name = item.title;
      }
    });
  };
  loop(tree, id);
  return name;
};

export default ({ visible, roleId, closeDrawer }) => {
  const [initialLoading, setInitialLoading] = useState(true);
  const [menuTree, setMenuTree] = useState([]);
  const [authLoadingId, setAuthLoadingId] = useState('');
  const [checkedKeys, setCheckedKeys] = useState([]);
  const [halfCheckedKeys, setHalfCheckedKeys] = useState([]);
  const [actionLoading, setActionLoading] = useState(false);

  const [grainedAuthDrawerVisible, setGrainedAuthDrawerVisible] = useState(false);
  const [grainedAuthDrawerWithResourceId, setGrainedAuthDrawerWithResourceId] = useState('');

  const { childIds, fatherIds } = useMemo(() => {
    const currentChildIds = getChildIds(menuTree);
    const currentFatherIds = getFatherIds(menuTree);
    return { childIds: currentChildIds, fatherIds: currentFatherIds };
  }, [menuTree]);
  const resourceName = useMemo(
    () => getMenuNameById(menuTree, grainedAuthDrawerWithResourceId),
    [grainedAuthDrawerWithResourceId],
  );

  // 获取菜单资源树
  const getValidResourceFromTree = async () => {
    try {
      const res = await fetchValidResourceFromTree();
      return _.isArray(res)
        ? formatTree(res, ({ id, title, description, resStatus, isHasComponent, children }) => ({
            key: id,
            title: title || '',
            description: description || '',
            disabledItem: resStatus !== '1', // 节点是否禁用
            selectable: _.isEmpty(children) ? !!isHasComponent : false, // 是否有二级权限管理（TODO：后期应包括数据权限的判断）
          }))
        : [];
    } catch (e) {
      return [];
    }
  };
  // 根据角色Id获取已授权的菜单节点
  const getResourceAuthByRoleId = async (roleId) => {
    try {
      const res = await fetchResourceAuthByRoleId({ roleId });
      return _.isArray(res) ? res : [];
    } catch (e) {
      return [];
    }
  };

  // 初始化
  useEffect(() => {
    getValidResourceFromTree().then((tree) => {
      setMenuTree(tree);
      setInitialLoading(false);
    });
  }, []);
  useEffect(() => {
    if (!_.isEmpty(menuTree)) {
      if (visible) {
        const nextAuthLoadingId = nanoid(12);
        setAuthLoadingId(nextAuthLoadingId);
        getResourceAuthByRoleId(roleId).then((checkedIds) => {
          let validDataFetch;
          setAuthLoadingId((currentId) => {
            if (currentId === nextAuthLoadingId) {
              validDataFetch = true;
              return '';
            }
            return currentId;
          });
          if (validDataFetch) {
            // 排除菜单节点删除之前授权的id
            const nextCheckedKeys = _.filter(checkedIds, (id) => _.includes(childIds, id));
            const nextHalfCheckedKeys = _.filter(checkedIds, (id) => _.includes(fatherIds, id));
            setCheckedKeys(nextCheckedKeys);
            setHalfCheckedKeys(nextHalfCheckedKeys);
          }
        });
        return;
      }
      setCheckedKeys([]);
      setHalfCheckedKeys([]);
      setAuthLoadingId('');
    }
  }, [visible, menuTree]);

  // 交互勾选
  const handleCheck = (nextCheckedKeys, { halfCheckedKeys: nextHalfCheckedKeys }) => {
    setCheckedKeys(nextCheckedKeys);
    setHalfCheckedKeys(nextHalfCheckedKeys);
  };
  // 选中节点（接口按钮权限、数据规则权限）
  const handleSelect = (resourceId) => {
    setGrainedAuthDrawerVisible(true);
    setGrainedAuthDrawerWithResourceId(resourceId);
  };

  const handleCancel = () => {
    if (!actionLoading) {
      closeDrawer();
    }
  };
  const handleConfirm = () => {
    setActionLoading(true);
    const params = { roleId, resIds: _.concat(checkedKeys, halfCheckedKeys) };
    updateResourceAuthByRoleId(params)
      .then(() => {
        closeDrawer();
        setActionLoading(false);
        message.success('角色菜单资源授权成功');
      })
      .catch(() => {
        setActionLoading(false);
      });
  };

  return (
    <Drawer
      visible={visible}
      title="菜单资源授权"
      bodyStyle={{ paddingBottom: 80 }}
      onClose={handleCancel}
      footer={
        <div className={styles.drawerFooterButtonContainer}>
          <DebounceButton
            disabled={actionLoading}
            onClick={handleCancel}
            style={{ marginRight: 8 }}
          >
            取消
          </DebounceButton>
          <DebounceButton
            onClick={handleConfirm}
            type="primary"
            loading={actionLoading}
            disabled={initialLoading || !!authLoadingId}
          >
            确定
          </DebounceButton>
        </div>
      }
    >
      <Spin spinning={initialLoading || !!authLoadingId} tip="加载中...">
        {menuTree.length ? (
          <Tree
            checkable
            defaultExpandAll
            treeData={menuTree}
            onCheck={handleCheck}
            checkedKeys={checkedKeys}
            titleRender={({ key, title, description, selectable, disabledItem }) => {
              return (
                <span
                  key={key}
                  title={description}
                  className={styles.menuNodeTitle}
                  onClick={() => {
                    if (selectable) {
                      handleSelect(key);
                    }
                  }}
                >
                  <span className={styles.menuNodeTitleText}>{title}</span>
                  {disabledItem && <span className={styles.menuDisabledIcon} />}
                  {selectable && <AlignLeftOutlined className={styles.menuExtraAuthIcon} />}
                </span>
              );
            }}
          />
        ) : (
          <Empty description={'暂无数据'} />
        )}
      </Spin>
      <GrainedAuthDrawer
        roleId={roleId}
        visible={grainedAuthDrawerVisible}
        resourceId={grainedAuthDrawerWithResourceId}
        resourceName={resourceName}
        closeDrawer={() => {
          setGrainedAuthDrawerVisible(false);
          setGrainedAuthDrawerWithResourceId('');
        }}
      />
    </Drawer>
  );
};
